home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / lib / rcscripts / net.modules.d / iwconfig < prev    next >
Text File  |  2006-04-25  |  25KB  |  890 lines

  1. # Copyright (c) 2004-2005 Gentoo Foundation
  2. # Distributed under the terms of the GNU General Public License v2
  3. # $Header$
  4.  
  5. # Contributed by Roy Marples (uberlord@gentoo.org)
  6. # Many thanks to all the people in the Gentoo forums for their ideas and
  7. # motivation for me to make this and keep on improving it
  8.  
  9. # Fix any potential localisation problems
  10. # Note that LC_ALL trumps LC_anything_else according to locale(7)
  11. iwconfig() {
  12.     LC_ALL=C /sbin/iwconfig "$@"
  13. }
  14. iwgetid() {
  15.     LC_ALL=C /sbin/iwgetid "$@"
  16. }
  17. iwlist() {
  18.     LC_ALL=C /sbin/iwlist "$@"
  19. }
  20. iwpriv() {
  21.     LC_ALL=C /sbin/iwpriv "$@"
  22. }
  23.  
  24. # void iwconfig_depend(void)
  25. #
  26. # Sets up the dependancies for the module
  27. iwconfig_depend() {
  28.     before interface
  29. }
  30.  
  31. # bool iwconfig_check_installed(void)
  32. #
  33. # Returns 1 if wireless-tools is installed, otherwise 0
  34. iwconfig_check_installed() {
  35.     [[ -x /sbin/iwconfig ]] && return 0
  36.     ${1:-false} && eerror "For Wireless (802.11) support, emerge net-wireless/wireless-tools"
  37.     return 1
  38. }
  39.  
  40. # char* iwconfig_provides(void)
  41. #
  42. # Returns a string to change module definition for starting up
  43. iwconfig_provides() {
  44.     echo "wireless"
  45. }
  46.  
  47. # bool iwconfig_check_depends(void)
  48. #
  49. # Checks to see if we have the needed functions
  50. iwconfig_check_depends() {
  51.     local f
  52.  
  53.     for f in interface_variable interface_up interface_down interface_exists; do
  54.         [[ $( type -t ${f} ) == function ]] && continue
  55.         eerror "iwconfig: missing required function ${f}\n"
  56.         return 1
  57.     done
  58.  
  59.     return 0
  60. }
  61.  
  62. # bool iwconfig_check_extensions(char *interface)
  63. #
  64. # Checks to see if wireless extensions are enabled on the interface
  65. iwconfig_check_extensions() {
  66.     local iface=${1}
  67.  
  68.     # Do we have wireless extensions enabled on the interface?
  69.     local ext=$( iwconfig ${iface} 2>/dev/null | awk -v iface=${iface} '{ if ($1 == iface) print "yes" }' )
  70.     [[ ${ext} == yes ]]
  71.     return $?
  72. }
  73.  
  74. # char* iwconfig_get_wep_status(char *interface)
  75. #
  76. # Echos a string showing whether WEP is enabled or disabled
  77. # for the given interface
  78. iwconfig_get_wep_status() {
  79.     local wep_status=$( iwconfig ${1} | awk -F: '/Encryption key:/ {print $2}' | awk '{if ($1 != "off") print "enabled"}' ) mode
  80.     wep_status=${wep_status:-"disabled"}
  81.  
  82.     [[ ${wep_status} == enabled ]] && mode=" - $( iwconfig ${1} | awk -F: '/Security mode:/ {print $3}' )"
  83.     
  84.     echo "(WEP ${wep_status}${mode})"
  85. }
  86.  
  87. # char* iwconfig_get_essid(char *iface)
  88. #
  89. # Gets the current ESSID of the iface
  90. iwconfig_get_essid() {
  91.     # Too many users are having with iwgetid atm :/
  92.     # iwgetid -r
  93.  
  94.     local i essid
  95.  
  96.     for (( i=0; i<5; i++ )); do
  97.         essid=$( iwconfig $1 2>/dev/null | awk -F\" '/ESSID/ {print $2}' )
  98.         if [[ -n ${essid} ]]; then
  99.             echo ${essid}
  100.             return 0
  101.         fi
  102.         sleep 1
  103.     done
  104.  
  105.     return 1
  106. }
  107.  
  108. # char* iwconfig_get_ap_mac_address(char *interface)
  109. #
  110. # Returns the MAC address of the Access Point
  111. # the interface is connected to
  112. iwconfig_get_ap_mac_address() {
  113.     iwgetid --ap ${1} 2>${devnull}| awk '{print $4}'
  114. }
  115.  
  116. # char* iwconfig_get_mode(char *interface)
  117. #
  118. # Returns the wireless mode in lower case
  119. iwconfig_get_mode() {
  120.     iwgetid --mode ${1} | awk -F: '{print $2}' | tr '[:upper:]' '[:lower:]'
  121. }
  122.  
  123. # char* iwconfig_get_type(char *interface)
  124. #
  125. # Returns the type of interface - the IEEE part
  126. iwconfig_get_type() {
  127.     iwconfig ${1} 2>/dev/null | awk '{print $2,$3}'
  128. }
  129.  
  130. # void iwconfig_report(char *interface)
  131. #
  132. # Output how our wireless interface has been configured
  133. iwconfig_report() {
  134.     local iface=${1} essid i=0 mac m="to"
  135.  
  136.     essid=$( iwconfig_get_essid ${iface} )
  137.  
  138.     local wep_status=$( iwconfig_get_wep_status ${iface} )
  139.     local channel=$( iwgetid --channel 2>/dev/null | cut -d: -f2 )
  140.     [[ -n ${channel} ]] && channel="on channel ${channel} "
  141.  
  142.     essid=${essid//\\\\/\\\\}
  143.     local mode=$( iwconfig_get_mode ${iface} )
  144.     if [[ ${mode} == "master" ]]; then
  145.         m="as"
  146.     else
  147.         mac=$( iwconfig_get_ap_mac_address ${iface} )
  148.         [[ -n ${mac} ]] && mac=" at ${mac}"
  149.     fi
  150.     
  151.     eindent
  152.     einfo "${iface} connected ${m} \"${essid}\"${mac}"
  153.     einfo "in ${mode} mode ${channel}${wep_status}"
  154.     eoutdent
  155. }
  156.  
  157. # char* iwconfig_get_wep_key(char *mac_address)
  158. #
  159. # Returns the configured WEP key for the given mac address
  160. # or the given ESSID. The mac address setting takes precendence
  161. iwconfig_get_wep_key() {
  162.     local mac=${1} key
  163.     eval key=\"\${mac_key_${mac//:/}\}\"
  164.     [[ -z ${key} ]] && eval key=\"\${key_${ESSIDVAR}\}\"
  165.     key=${key:-"off"}
  166.     echo ${key}
  167. }
  168.  
  169. # void iwconfig_user_config(char *iface)
  170. #
  171. # Applies the user configuration to the interface
  172. iwconfig_user_config() {
  173.     local iface=${1} conf e ifvar=$( interface_variable ${1} )
  174.  
  175.     # Apply the user configuration
  176.     eval conf=\"\$\{iwconfig_${ifvar}\}\"
  177.     if [[ -n ${conf} ]]; then
  178.         e=$( iwconfig ${iface} ${conf} 2>&1 )
  179.         if [[ -n ${e} ]]; then
  180.             ewarn "${iface} does not support the following configuration commands"
  181.             ewarn "  \"${conf}\""
  182.         fi
  183.     fi
  184.  
  185.     eval conf=\"\$\{iwpriv_${ifvar}\}\"
  186.     if [[ -n ${conf} ]]; then
  187.         e=$( iwpriv ${iface} ${conf} 2>&1 )
  188.         if [[ -n ${e} ]]; then
  189.             ewarn "${iface} does not support the following private ioctls"
  190.             ewarn "  \"${conf}\""
  191.         fi
  192.     fi
  193. }
  194.  
  195. # bool iwconfig_setup_specific(char *iface)
  196. #
  197. # Sets up our wireless interface to operate in ad-hoc or master mode
  198. iwconfig_setup_specific() {
  199.     local iface=${1} mode=${2} channel key dessid e
  200.     local ifvar=$( interface_variable ${1} )
  201.  
  202.     if [[ -z ${ESSID} ]]; then
  203.         eerror "${iface} requires an ESSID to be set to operate in ${mode} mode"
  204.         eerror "adjust the essid_${iface} setting in /etc/conf.d/wireless"
  205.         return 1
  206.     fi
  207.     dessid=${ESSID//\\\\/\\\\}
  208.     LC_ALL=C ESSIDVAR=${ESSID//[![:word:]]/_}
  209.  
  210.     # We only change the mode if it's not the same
  211.     local cur_mode=$( iwconfig_get_mode ${iface} )
  212.     if [[ ${cur_mode} != ${mode} ]]; then
  213.         e=$( iwconfig ${iface} mode ${mode} 2>&1 )
  214.         if [[ -n ${e} ]]; then
  215.             eerror "${iface} does not support setting the mode to \"${mode}\""
  216.             return 1
  217.         fi
  218.     fi
  219.  
  220.     key=$( iwconfig_get_wep_key )
  221.     e=$( eval "iwconfig ${iface} key ${key} 2>&1" )
  222.     if [[ -n ${e} && ${key} != off ]]; then
  223.         ewarn "${iface} does not support setting keys"
  224.         ewarn "or the parameter \"mac_key_${ESSIDVAR}\" or \"key_${ESSIDVAR}\" is incorrect"
  225.     fi
  226.  
  227.     e=$( iwconfig ${iface} essid "${ESSID}" 2>&1 )
  228.     if [[ -n ${e} ]]; then
  229.         eerror "${iface} does not support setting ESSID to \"${dessid}\""
  230.         return 1
  231.     fi
  232.     iwconfig ${iface} nick "${ESSID}" 2>/dev/null
  233.  
  234.     eval channel=\"\$\{channel_${ifvar}\}\"
  235.     # We default the channel to 3
  236.     channel=${channel:-3}
  237.  
  238.     e=$( iwconfig ${iface} channel ${channel} 2>&1 )
  239.     if [[ -n ${e} ]]; then
  240.         eerror ${e}
  241.         ewarn "${iface} does not support setting the channel to \"${channel}\""
  242.         return 1
  243.     fi
  244.  
  245.     iwconfig_user_config ${iface}
  246.     iwconfig_report ${iface}
  247.  
  248.     return 0
  249. }
  250.  
  251. # bool iwconfig_associate_mac(char *iface)
  252. #
  253. # Returns true if the AP MAC address is valid or not
  254. iwconfig_associate_mac() {
  255.     # Checks if a MAC address has been assigned
  256.     local mac=$( iwconfig_get_ap_mac_address ${1} ) i
  257.     local -a invalid_macs=( "00:00:00:00:00:00" "44:44:44:44:44:44" "FF:00:00:00:00:00" "FF:FF:FF:FF:FF:FF" )
  258.  
  259.     [[ -z ${mac} ]] && return 1
  260.     for i in ${invalid_macs[@]}; do
  261.         [[ ${i} == ${mac} ]] && return 1
  262.     done
  263.     return 0
  264. }
  265.  
  266. # bool iwconfig_associate_quality(char *iface)
  267. #
  268. # Returns true if the link quality is not 0 or 0.
  269. iwconfig_associate_quality() {
  270.     local quality=$( cat /proc/net/wireless | awk -v IFACE=${1}: '{ if ($1 == IFACE) print $3 }' )
  271.     [[ ${quality} != 0 && ${quality} != 0. ]] && return 0
  272.     return 1
  273. }
  274.  
  275. # bool iwconfig_test_associated(char *iface)
  276. #
  277. # Returns true if the interface has associated with an Access Point
  278. iwconfig_test_associated() {
  279.     local iface=${1} test ifvar=$( interface_variable ${1} )
  280.     # Some drivers don't set MAC to a bogus value when assocation is lost/fails
  281.     # whereas they do set link quality to 0
  282.  
  283.     test=$( eval echo \$\{associate_test_${ifvar}\} | tr '[:upper:]' '[:lower:]' )
  284.     test=${test:-mac}
  285.     if [[ ${test} != mac && ${test} != quality && ${test} != all ]]; then
  286.         ewarn "  associate_test_${iface} is not set to mac, quality or all"
  287.         ewarn "  defaulting to \"mac\""
  288.         test=mac
  289.     fi
  290.  
  291.     case ${test} in
  292.         mac) iwconfig_associate_mac ${iface} && return 0 ;;
  293.         quality) iwconfig_associate_quality ${iface} && return 0 ;;
  294.         all) iwconfig_associate_mac ${iface} && iwconfig_associate_quality ${iface} && return 0 ;;
  295.     esac
  296.  
  297.     return 1
  298. }
  299.  
  300. # bool iwconfig_wait_for_association(char *iface)
  301. #
  302. # Waits for a configured ammount of time until
  303. # we are assocaited with an Access Point
  304. iwconfig_wait_for_association() {
  305.     local iface=${1} i=0 wait ifvar=$( interface_variable ${1} )
  306.     eval wait=\"\$\{sleep_associate_${ifvar}\}\"
  307.     wait=${wait:-10}
  308.  
  309.     while (( i<wait )); do
  310.         iwconfig_test_associated ${iface} && return 0
  311.         sleep 1
  312.         (( i++ ))
  313.     done
  314.     return 1
  315. }
  316.  
  317. # bool iwconfig_associate(char *interface, char *mac_address, char *wep_required)
  318. #
  319. # Tries to associate the interface with an Access Point
  320. # If we scanned the Access Point we know if we need WEP to associate or not
  321. # and if we have a WEP key for the ESSID or not
  322. # so we can fail gracefully without even trying to connect
  323. iwconfig_associate() {
  324.     local iface=${1} mac=${2} wep_required=${3} w="(WEP Disabled)"
  325.     local dessid=${ESSID//\\\\/\\\\} key
  326.     wep_required=${wep_required:-"off"}
  327.  
  328.     if [[ ${ESSID} == any ]]; then
  329.         iwconfig ${iface} ap any 2>/dev/null
  330.         dessid="any"
  331.         unset ESSIDVAR
  332.     else
  333.         LC_ALL=C ESSIDVAR=${ESSID//[![:word:]]/_}
  334.         key=$( iwconfig_get_wep_key ${mac} )
  335.         if [[ ${wep_required} == yes && ${key} == off ]]; then
  336.             vewarn "WEP key is not set for \"${dessid}\" - not connecting"
  337.             return 1
  338.         fi
  339.         if [[ ${wep_required} == no && ${key} != off ]]; then
  340.             key="off"
  341.             vewarn "\"${dessid}\" is not WEP enabled - ignoring setting"
  342.         fi
  343.  
  344.         e=$( eval "iwconfig ${iface} key ${key} 2>&1" )
  345.         if [[ -n ${e} && ${key} != off ]]; then
  346.             ewarn "${iface} does not support setting keys"
  347.             ewarn "or the parameter \"mac_key_${ESSIDVAR}\" or \"key_${ESSIDVAR}\" is incorrect"
  348.             return 1
  349.         fi
  350.         [[ ${key} != off ]] && w=$( iwconfig_get_wep_status ${iface} )
  351.     fi
  352.  
  353.     e=$( iwconfig ${iface} essid "${ESSID}" 2>&1 )
  354.     [[ -n ${e} && ${ESSID} != any ]] && ewarn "${iface} does not support setting ESSID to \"${dessid}\""
  355.     iwconfig ${iface} nick "${ESSID}" 2>/dev/null
  356.  
  357.     vebegin "Connecting to \"${dessid}\" ${w}"
  358.  
  359.     if [[ ${ESSID} != any && $( type -t preassociate ) == function ]]; then
  360.         local essidx=${ESSID} essidvarx=${ESSIDVAR}
  361.         veinfo "Running preassociate function"
  362.         eindent
  363.         preassociate ${iface} ; e=$?
  364.         eoutdent
  365.         if [[ ${e} != 0 ]]; then
  366.             veend 1 "preassociate \"${dessid}\" on ${iface} failed"
  367.             return 1
  368.         fi
  369.         ESSID=${essidx} ESSIDVAR=${essidvarx}
  370.     fi
  371.  
  372.     if ! iwconfig_wait_for_association ${iface} ; then
  373.         veend 1
  374.         return 1
  375.     fi
  376.     veend 0
  377.  
  378.     if [[ ${ESSID} == any ]]; then
  379.         ESSID=$( iwconfig_get_essid ${iface} )
  380.         iwconfig_associate ${iface}
  381.         return $?
  382.     fi
  383.  
  384.     iwconfig_user_config ${iface}    
  385.     iwconfig_report ${iface}
  386.  
  387.     if [[ $( type -t postassociate ) == function ]]; then
  388.         local essidx=${ESSID} essidvarx=${ESSIDVAR}
  389.         veinfo "Running postassociate function"
  390.         eindent
  391.         postassociate ${iface}
  392.         eoutdent
  393.         ESSID=${essidx} ESSIDVAR=${essidvarx}
  394.     fi
  395.  
  396.     return 0
  397. }
  398.  
  399. # bool iwconfig_scan(char *iface)
  400. #
  401. # Fills 3 arrays with information from a wireless scan
  402. iwconfig_scan() {
  403.     local iface=${1} e mode x ifvar=$( interface_variable ${1} )
  404.  
  405.     # First, we may need to change mode to scan in
  406.     mode=$( eval echo \$\{scan_mode_${ifvar}\} | tr '[:upper:]' '[:lower:]' )
  407.     if [[ -n ${mode} ]]; then
  408.         e=$( iwconfig ${iface} mode ${mode} 2>&1 )
  409.         [[ -n ${e} ]] && ewarn "${iface} does not support setting the mode to \"${mode}\""
  410.     fi
  411.  
  412.     # Next we set any private driver ioctls needed
  413.     eval x=\"\$\{iwpriv_scan_pre_${ifvar}\}\"
  414.     if [[ -n ${x} ]]; then
  415.         e=$( iwpriv ${iface} ${x} 2>&1 )
  416.         if [[ -n ${e} ]]; then
  417.             ewarn "${iface} does not support the following private ioctls" \
  418.             ewarn "  \"${x}\""
  419.         fi
  420.     fi
  421.  
  422.     veinfo "Scanning for access points"
  423.  
  424.     # Sleep if required
  425.     eval x=\"\$\{sleep_scan_${ifvar}\}\"
  426.     [[ -n ${x} ]] && sleep ${x}
  427.  
  428.     local scan=$( iwlist ${iface} scanning 2>/dev/null )
  429.  
  430.     # We may need to unset the previous private driver ioctls
  431.     eval x=\"\$\{iwpriv_scan_post_${ifvar}\}\"
  432.     if [[ -n ${x} ]]; then
  433.         e=$( iwpriv ${iface} ${x} 2>&1 )
  434.         if [[ -n ${e} ]]; then
  435.             ewarn "${iface} does not support the following private ioctls" \
  436.             ewarn "  \"${x}\""
  437.         fi
  438.     fi
  439.  
  440.     # Change back mode if needed
  441.     x=$( eval echo \$\{mode_${ifvar}\} | tr '[:upper:]' '[:lower:]' )
  442.     x=${x:-auto}
  443.     [[ ${mode} != ${x} ]] && iwconfig ${iface} mode ${x} &>/dev/null
  444.  
  445.     # HUP the interface as some drivers/cards need it
  446.     interface_down ${iface}
  447.     interface_up ${iface}            
  448.  
  449.     if [[ -z ${scan} ]]; then
  450.         ewarn "${iface} does not support scanning"
  451.         eval x=\"\$\{adhoc_essid_${ifvar}\}\"
  452.         [[ -n ${x} ]] && return 0
  453.         if [[ -n ${preferred_aps} ]]; then
  454.             [[ ${associate_order} == forcepreferred \
  455.             || ${associate_order} == forcepreferredonly ]] && return 0
  456.         fi
  457.         eerror "You either need to set a preferred_aps list in /etc/conf.d/wireless"
  458.         eerror "   preferred_aps=( \"ESSID1\" \"ESSID2\" )"
  459.         eerror "   and set associate_order_${iface}=\"forcepreferred\""
  460.         eerror "   or set associate_order_${iface}=\"forcepreferredonly\""
  461.         eerror "or hardcode the ESSID to \"any\" and let the driver find an Access Point"
  462.         eerror "   essid_${iface}=\"any\""
  463.         eerror "or configure defaulting to Ad-Hoc when Managed fails"
  464.         eerror "   adhoc_essid_${iface}=\"WLAN\""
  465.         eerror "or hardcode the ESSID against the interface (not recommended)"
  466.         eerror "   essid_${iface}=\"ESSID\""
  467.         return 1
  468.     fi
  469.  
  470.     local val i=-1 IFS=$'\n' j last
  471.     local -a qual
  472.  
  473.     # OK - we need ESSID, MAC address and encryption from just one call to iwlist $iface scan
  474.     # It has to be one call for speed reasons as some cards take ages to get a list from
  475.     # It's clumsy (imo) but it works
  476.     for val in ${scan}; do
  477.         local t=$( echo ${val} | awk -F: '/ESSID/ {print $2}' )
  478.         if [[ ${#t} -gt 2 ]]; then
  479.             t=${t#*\"}
  480.             essid_APs[i]=${t%*\"}
  481.         else
  482.             t=$( echo ${val} | awk '/Address/ {print}' | sed 's/^.*\<\(..:..:..:..:..:..\)\>.*$/\1/g' )
  483.             if [[ ${#t} -gt 0 ]]; then
  484.                 ((i++))
  485.                 mac_APs[i]=${t}
  486.                 essid_APs[i]=""
  487.                 enc_APs[i]=no
  488.                 qual[i]=0
  489.             else
  490.                 t=$( echo ${val} | awk -F: '/Encryption key/ {print $2}' )
  491.                 if [[ ${#t} -gt 0 ]]; then
  492.                     if [[ ${t} == off ]]; then
  493.                         enc_APs[i]=no
  494.                     else
  495.                         enc_APs[i]=yes
  496.                     fi
  497.                 else
  498.                     t=$( echo ${val} | awk -F: '/Quality/ {print $2}' )
  499.                     if [[ ${#t} -gt 0 ]]; then
  500.                         # Not all drivers report the same way, so we take the below measure
  501.                         # to ensure we don't error on the sort below
  502.                         t=${t# *}
  503.                         t=${t%/*}
  504.                         t=${t//[![:digit:]]/}
  505.                         qual[i]=${t:-0}
  506.                     fi
  507.                 fi
  508.             fi
  509.         fi
  510.     done
  511.  
  512.     # Now sort the AP's by quality
  513.     for ((last=${#mac_APs[@]}-1; last>0; last--)); do
  514.         for ((i=0; i<${last}; i++)); do
  515.             (( j = i + 1 ))
  516.             if [[ ${qual[i]} -lt ${qual[j]} ]]; then
  517.                 t=${mac_APs[i]}
  518.                 mac_APs[i]=${mac_APs[j]}
  519.                 mac_APs[j]=${t}
  520.                 t=${essid_APs[i]}
  521.                 essid_APs[i]=${essid_APs[j]}
  522.                 essid_APs[j]=${t}
  523.                 t=${enc_APs[i]}
  524.                 enc_APs[i]=${enc_APs[j]}
  525.                 enc_APs[j]=${t}
  526.                 t=${qual[i]}
  527.                 qual[i]=${qual[j]}
  528.                 qual[j]=${t}
  529.             fi
  530.         done
  531.     done
  532.  
  533.     return 0
  534. }
  535.  
  536. # void iwconfig_scan_report(void)
  537. #
  538. # Report the results of the scan and re-map any ESSIDs if they
  539. # have been configured for the MAC address found
  540. iwconfig_scan_report() {
  541.     local i k m remove
  542.     local -a u
  543.  
  544.     [[ -z ${mac_APs} ]] && ewarn "  no access points found"
  545.  
  546.     # We need to do the for loop like this so we can
  547.     # dynamically remove from the array
  548.     eindent
  549.     for ((i=0; i<${#mac_APs[@]}; i++)); do
  550.         k=""
  551.         [[ ${enc_APs[i]} == yes ]] && k="(WEP required)"
  552.  
  553.         if [[ -z ${essid_APs[i]} ]]; then
  554.             veinfo "Found ${mac_APs[i]} ${k}"
  555.         else
  556.             veinfo "Found \"${essid_APs[i]//\\\\/\\\\}\" at ${mac_APs[i]} ${k}"
  557.         fi
  558.  
  559.         eindent
  560.  
  561.         eval m=\"\$\{mac_essid_${mac_APs[i]//:/}\}\"
  562.         if [[ -n ${m} ]]; then
  563.             essid_APs[i]=${m}
  564.             veinfo "mapping to \"${m//\\\\/\\\\}\""
  565.         fi
  566.  
  567.         remove=false
  568.         # If we don't know the essid then we cannot connect to them
  569.         # so we remove them from our array
  570.         if [[ -z ${essid_APs[i]} ]]; then
  571.             remove=true
  572.         else
  573.             for k in "${blacklist_aps[@]}"; do
  574.                 if [[ ${k} == ${essid_APs[i]} ]]; then
  575.                     vewarn "\"${k//\\\\/\\\\}\" has been blacklisted - not connecting"
  576.                     remove=true
  577.                     break
  578.                 fi
  579.             done
  580.         fi
  581.  
  582.         eoutdent
  583.  
  584.         ${remove} && u=( "${u[@]}" "${i}" )
  585.     done
  586.  
  587.     eoutdent
  588.  
  589.     # Now we remove any duplicates
  590.     for ((i=0; i < ${#essid_APs[@]} - 1; i++)); do
  591.         for ((j=${i} + 1; j <${#essid_APs[@]}; j++)); do
  592.             [[ ${essid_APs[i]} == ${essid_APs[j]} ]] && u=( "${u[@]}" "${j}" )
  593.         done
  594.     done
  595.  
  596.     for i in ${u[@]}; do
  597.         unset essid_APs[i]
  598.         unset mac_APs[i]
  599.         unset enc_APs[i]
  600.     done
  601.  
  602.     # We need to squash our arrays so indexes work again
  603.     essid_APs=( "${essid_APs[@]}" )
  604.     mac_APs=( "${mac_APs[@]}" )
  605.     enc_APs=( "${enc_APs[@]}" )
  606. }
  607.  
  608. # bool iwconfig_force_preferred(char *iface)
  609. #
  610. # Forces the preferred_aps list to associate in order
  611. # but only if they were not picked up by our scan
  612. iwconfig_force_preferred() {
  613.     local iface=${1} essid i
  614.  
  615.     [[ -z ${preferred_aps} ]] && return 1
  616.  
  617.     ewarn "Trying to force preferred in case they are hidden"
  618.     for essid in "${preferred_aps[@]}"; do
  619.         local found_AP=false
  620.         for ((i = 0; i < ${#mac_APs[@]}; i++)); do
  621.             if [[ ${essid} == ${essid_APs[i]} ]]; then
  622.                 found_AP=true
  623.                 break
  624.             fi
  625.         done
  626.         if ! ${found_AP} ; then
  627.             ESSID=${essid}
  628.             iwconfig_associate ${iface} && return 0
  629.         fi
  630.     done
  631.  
  632.     ewarn "Failed to associate with any preferred access points on ${iface}"
  633.     return 1
  634. }
  635.  
  636. # bool iwconfig_connect_preferred(char *iface)
  637. #
  638. # Connects to preferred_aps in order if they were picked up
  639. # by our scan
  640. iwconfig_connect_preferred() {
  641.     local iface=${1} essid i
  642.  
  643.     for essid in "${preferred_aps[@]}"; do
  644.         for ((i=0; i<${#essid_APs[@]}; i++)); do
  645.             if [[ ${essid} == ${essid_APs[i]} ]]; then
  646.                 ESSID=${essid}
  647.                 iwconfig_associate ${iface} ${mac_APs[i]} ${enc_APs[i]} && return 0
  648.                 break
  649.             fi
  650.         done
  651.     done
  652.  
  653.     return 1
  654. }
  655.  
  656. # bool iwconfig_connect_not_preferred(char *iface)
  657. #
  658. # Connects to any AP's found that are not in
  659. # our preferred list
  660. iwconfig_connect_not_preferred() {
  661.     local iface=${1} i ap has_preferred
  662.  
  663.     for ((i=0; i<${#mac_APs[@]}; i++)); do
  664.         has_preferred=false
  665.         for ap in "${preferred_aps[@]}"; do
  666.             if [[ ${ap} == ${essid_APs[i]} ]]; then
  667.                 has_preferred=true
  668.                 break
  669.             fi
  670.         done
  671.         if ! ${has_preferred} ; then
  672.             ESSID=${essid_APs[i]}
  673.             iwconfig_associate ${iface} ${mac_APs[i]} ${enc_APs[i]} && return 0
  674.         fi
  675.     done
  676.  
  677.     return 1
  678. }
  679.  
  680. # void iwconfig_defaults(char *iface)
  681. #
  682. # Apply some sane defaults to the wireless interface
  683. # incase the user already applied some changes
  684. iwconfig_defaults() {
  685.     local iface=${1}
  686.  
  687.     # Set some defaults
  688.     iwconfig ${iface} rate auto &>/dev/null
  689.     iwconfig ${iface} rts off &>/dev/null
  690.     iwconfig ${iface} frag off &>/dev/null
  691.     iwconfig ${iface} power off &>/dev/null
  692.     iwconfig ${iface} txpower auto &>/dev/null
  693.     iwconfig ${iface} key off [1] &>/dev/null
  694.  
  695.     # We need to set the essid to any as some drivers won't
  696.     # scan correctly if they are already set to an ESSID
  697.     iwconfig ${iface} essid any &>/dev/null
  698. }
  699.  
  700. # void iwconfig_strip_associated(char *iface)
  701. #
  702. # We check to see which ifaces have associated AP's except for the iface
  703. # given and remove those AP's from the scan list
  704. # We also remove from the preferred list
  705. iwconfig_strip_associated() {
  706.     local iface=${1} e a j
  707.     local essid=$( iwconfig ${iface} | awk -F\" '/ESSID/ {print $2}' )
  708.     local -a ifaces=( $( iwconfig 2>/dev/null | awk '/ESSID/ {print $1}' | awk -v IFACE=${iface} '$1!=IFACE {print}' ) )
  709.  
  710.     for i in "${ifaces[@]}"; do
  711.         interface_is_up ${i} || continue
  712.         iwconfig_test_associated ${i} || continue
  713.         e=$( iwconfig ${i} | awk -F\" '/ESSID/ {print $2}' )
  714.         u=()
  715.         for ((j=0; j<${#mac_APs[@]}; j++)); do
  716.             if [[ ${essid_APs[j]} == ${e} ]]; then
  717.                 ewarn "${e} has already been associated with ${i}"
  718.                 unset essid_APs[j]
  719.                 unset mac_APs[j]
  720.                 unset enc_APs[j]
  721.                 # We need to squash our arrays so that indexes work
  722.                 essid_APs=( "${essid_APs[@]}" )
  723.                 mac_APs=( "${mac_APs[@]}" )
  724.                 enc_APs=( "${enc_APs[@]}" )
  725.                 break
  726.             fi
  727.         done
  728.         for ((j=0; j<${#preferred_aps[@]}; j++)); do
  729.             if [[ ${preferred_aps[j]} == ${e} ]]; then
  730.                 unset preferred_aps[j]
  731.                 preferred_aps=( "${preferred_aps[@]}" )
  732.                 break
  733.             fi
  734.         done
  735.     done
  736. }
  737.  
  738. # bool iwconfig_configure(char *iface)
  739. #
  740. # The main startup code
  741. # First we bring the interface up, apply defaults, apply user configuration
  742. # Then we test to see if ad-hoc mode has been requested and branch if needed
  743. # Then we scan for access points and try to connect to them in a predetermined order
  744. # Once we're connected we show a report and then configure any interface
  745. # variables for the ESSID
  746. iwconfig_configure() {
  747.     local iface=${1} test x e ifvar=$( interface_variable ${1} )
  748.     local -a essid_APs mac_APs enc_APs
  749.  
  750.     # We need to bring the interface up to apply stuff
  751.     interface_up ${iface}
  752.  
  753.     # Are we a proper IEEE device?
  754.     # Most devices reutrn IEEE 802.11b/g - but intel cards return IEEE in lower case
  755.     # and RA cards return RAPCI or similar which really sucks :(
  756.     # For the time being, we will test prism54 not loading firmware which reports
  757.     # NOT READY!
  758.     x=$( iwconfig_get_type ${iface} )
  759.     if [[ ${x} == "NOT READY!" ]]; then
  760.         eerror "Looks like there was a probem loading the firmware for ${iface}"
  761.         return 1
  762.     fi
  763.     
  764.     iwconfig_defaults ${iface}
  765.     iwconfig_user_config ${iface}
  766.  
  767.     eval ESSID=\"\$\{essid_${ifvar}\}\"
  768.  
  769.     # Setup ad-hoc mode?
  770.     x=$( eval echo \$\{mode_${ifvar}\} | tr '[:upper:]' '[:lower:]' )
  771.     x=${x:-managed}
  772.     if [[ ${x} == ad-hoc || ${x} == master ]]; then
  773.         iwconfig_setup_specific ${iface} ${x}
  774.         return $?
  775.     fi
  776.  
  777.     if [[ ${x} != managed  && ${x} != auto ]]; then
  778.         eerror "Only managed, ad-hoc, master and auto modes are supported"
  779.         return 1
  780.     fi
  781.  
  782.     # We only change the mode if it's not the same as some drivers
  783.     # only do managed and throw an error changing to managed
  784.     local cur_mode=$( iwconfig_get_mode ${iface} )
  785.     if [[ ${cur_mode} != ${x} ]]; then
  786.         e=$( iwconfig ${iface} mode ${x} 2>&1 )
  787.         if [[ -n ${e} && ${x} != managed ]]; then
  788.             eerror "${iface} does not support setting the mode to \"${x}\""
  789.             return 1
  790.         fi
  791.     fi
  792.  
  793.     # These arrays hold the results of our scan
  794.     local -a mac_APs essid_APs enc_APs
  795.  
  796.     # Has an ESSID been forced?
  797.     if [[ -n ${ESSID} ]]; then
  798.         iwconfig_associate ${iface} && return 0
  799.         [[ ${ESSID} == any ]] && iwconfig_force_preferred ${iface} && return 0
  800.         eval ESSID=\"\$\{adhoc_essid_${ifvar}\}\"
  801.         if [[ -n ${ESSID} ]]; then
  802.             iwconfig_setup_specific ${iface} ad-hoc
  803.             return $?
  804.         fi
  805.         return 1
  806.     fi
  807.  
  808.     # Do we have a preferred Access Point list specific to the interface?
  809.     eval x=( \"\$\{preferred_aps_${ifvar}\[@\]\}\" )
  810.     [[ -n ${x} ]] && preferred_aps=( "${x[@]}" )
  811.  
  812.     # Do we have a blacklist Access Point list specific to the interface?
  813.     eval x=( \"\$\{blacklist_aps_${ifvar}\[@\]\}\" )
  814.     [[ -n ${e} ]] && blacklist_aps=( "${x[@]}" )
  815.  
  816.     # Are we forcing preferred only?
  817.     eval x=\"\$\{associate_order_${ifvar}\}\"
  818.     [[ -n ${x} ]] && associate_order=${x}
  819.     associate_order=$( echo ${associate_order:-any} | tr '[:upper:]' '[:lower:]' )
  820.  
  821.     if [[ ${associate_order} == forcepreferredonly ]]; then
  822.         iwconfig_force_preferred ${iface} && return 0
  823.     else
  824.         iwconfig_scan ${iface} || return 1
  825.         iwconfig_scan_report
  826.  
  827.         # Strip AP's from the list that have already been associated with
  828.         # other wireless cards in the system if requested
  829.         eval x=\"\$\{unique_ap_${ifvar}\}\"
  830.         [[ -n ${x} ]] && unique_ap=${x}
  831.         unique_ap=$( echo ${unique_ap:-no} | tr '[:upper:]' '[:lower:]' )
  832.         [[ ${unique_ap} != no ]] && iwconfig_strip_associated ${iface}
  833.  
  834.         iwconfig_connect_preferred ${iface} && return 0
  835.         [[ ${associate_order} == forcepreferred || ${associate_order} == forceany ]] && iwconfig_force_preferred ${iface} && return 0
  836.         [[ ${associate_order} == any || ${associate_order} == forceany ]] && iwconfig_connect_not_preferred ${iface} && return 0
  837.     fi
  838.  
  839.     e="associate with"
  840.     [[ -z ${mac_APs} ]] && e="find"
  841.     [[ ${preferred_only} == force || ${preferred_aps} == forceonly ]] && e="force"
  842.     e="Couldn't ${e} any access points on ${iface}"
  843.     
  844.     eval ESSID=\"\$\{adhoc_essid_${ifvar}\}\"
  845.     if [[ -n ${ESSID} ]]; then
  846.         ewarn "${e}"
  847.         iwconfig_setup_specific ${iface} ad-hoc
  848.         return $?
  849.     fi
  850.  
  851.     eerror ${e}
  852.     return 1
  853. }
  854.  
  855. # bool iwconfig_pre_start(char *iface)
  856. #
  857. # Start entry point
  858. # First we check if wireless extensions exist on the interface
  859. # If they are then we configue wireless
  860. iwconfig_pre_start() {
  861.     local iface=${1} r=0 local wasup=true
  862.  
  863.     interface_exists ${iface} || return 0
  864.  
  865.     if ! iwconfig_check_extensions ${iface} ; then
  866.         if ! interface_is_up ${iface} ; then
  867.             interface_up ${iface}
  868.             wasup=false
  869.         fi
  870.         if ! iwconfig_check_extensions ${iface} ; then
  871.             veinfo "Wireless extensions not found for ${iface}"
  872.             ! ${wasup} && interface_down ${iface}
  873.             return 0
  874.         fi
  875.     fi
  876.  
  877.     einfo "Configuring wireless network for ${iface}"
  878.  
  879.     # Setup IFS incase parent script has modified it
  880.     local IFS=$' '$'\n'$'\t'
  881.  
  882.     iwconfig_configure ${iface} && return 0
  883.  
  884.     eerror "Failed to configure wireless for ${iface}"
  885.     iwconfig_defaults ${iface}
  886.     unset ESSID
  887.     interface_down ${iface}
  888.     return 1
  889. }
  890.